/*
 * @Author: xiaosihan 
 * @Date: 2021-04-30 22:13:23 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2021-11-07 15:02:08
 */

import React from "react";
import * as THREE from "three";
import Mesh from "../Mesh/Mesh";
import Object3D from "../Object3D/Object3D";
import Object3DComponent, { Object3DComponentProps } from "../Object3D/Object3DComponent";
import Transition from "../xrt_util/Transition";
import TransitionColor from "../xrt_util/TransitionColor";

export interface HemisphereLightProps extends Object3DComponentProps {
    /**
     *天光颜色 "#fff"
     */
    skyColor?: string,
    /**
     *背光颜色 "#444"
     */
    groundColor?: string,
    /**
     * 光照强度 0-1
     */
    intensity?: number
}

interface State {
}

const ball = new THREE.SphereBufferGeometry(1, 20, 20);


/**
 * 半球光
 */
export default class HemisphereLight extends Object3DComponent<HemisphereLightProps, State> {
    constructor(props: HemisphereLightProps) {
        super(props);

        this.object3d.add(this.hemisphereLight);
    }

    static defaultProps = {
        skyColor: "#fff",
        groundColor: "#444",
        intensity: 1
    };


    hemisphereLight = new THREE.HemisphereLight();

    declare object3d: THREE.HemisphereLight & Object3D;

    // 天光颜色缓动对象
    Tcolor = new TransitionColor(this.props.skyColor || "#fff");

    // 背光颜色缓动对象
    TgroundColor = new TransitionColor(this.props.groundColor || "#444");

    // 灯光参数
    lightParams = new Transition();

    // 天光helper着色器
    materia = new THREE.ShaderMaterial({
        transparent: true,
        side: THREE.FrontSide,
        uniforms: {
            skyColor: {
                value: new THREE.Color(this.props.skyColor || "#fff")
            },
            groundColor: {
                value: new THREE.Color(this.props.groundColor || "#444")
            }
        },
        vertexShader: `
            varying vec2 vUv;
            void main() {
                vUv = uv;
                gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
            }
        `,
        fragmentShader: `
            uniform vec3 skyColor;
            uniform vec3 groundColor;
            varying vec2 vUv;
            
            void main() {
                float r = mix(skyColor.r, groundColor.r, 1.0 - vUv.y);
                float g = mix(skyColor.g, groundColor.g, 1.0 - vUv.y);
                float b = mix(skyColor.b, groundColor.b, 1.0 - vUv.y);
                gl_FragColor = vec4(r, g, b, 0.8);
            }
        `
    });

    componentBeforeRender(renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera) {
        let keepRun = this.setLightParam();
        return keepRun;
    }

    // 设置灯光的参数
    setLightParam() {
        let keepRun = false;

        // 天光颜色
        if (!this.Tcolor.isDone()) {
            const { r, g, b } = this.Tcolor.getJson();
            this.hemisphereLight.color.setRGB(r, g, b);
            this.materia.uniforms.skyColor.value.setRGB(r, g, b);
            keepRun = true;
        }

        // 背光光颜色
        if (!this.TgroundColor.isDone()) {
            const { r, g, b } = this.TgroundColor.getJson();
            this.hemisphereLight.groundColor.setRGB(r, g, b);
            this.materia.uniforms.groundColor.value.setRGB(r, g, b);
            keepRun = true;
        }

        // 光照强度
        if (!this.lightParams.isDone()) {
            const { intensity } = this.lightParams.getJson();
            Object.assign(this.hemisphereLight, {
                intensity
            })
            keepRun = true;
        }

        return keepRun;
    }

    // 设置灯光的过渡参数
    setLightTansParam() {
        const {
            bezier,
            duration = 500,
            skyColor = "#fff",
            groundColor = "#444",
            intensity = 1
        } = this.props;

        this.Tcolor.setBezier(bezier).setDuration(duration).set(skyColor);

        this.TgroundColor.setBezier(bezier).setDuration(duration).set(groundColor);

        this.lightParams.setBezier(bezier).setDuration(duration).set({ intensity });
    }

    componentDidMount() {
        this.setLightTansParam();
        this.setLightParam();
    }

    componentDidUpdate() {
        this.setLightTansParam();
    }

    render() {

        const { dev } = this.context;

        if (!dev) {
            return null;
        }

        return (
            <Mesh
                duration={0}
                geometry={ball}
                material={this.materia}
                clipping={false}
                cursor="pointer"
                title={
                    <div
                        style={{
                            position: "relative",
                            backgroundColor: "rgba(0, 0, 0, 0.8)",
                            borderRadius: 4,
                            padding: "4px 8px",
                            color: "#fff"
                        }}
                    >
                        <span>{"半球光"}<br /></span>
                        <span>{"<HemisphereLight/>"}<br /></span>
                    </div>
                }
            />
        );
    }
}